package blog

import kotlin.properties.Delegates
import kotlin.reflect.KProperty

/**
 * 类委托
 */
interface Base {
    fun todo()
}

// 实现此接口的被委托的类
class BaseIml : Base {
    override fun todo() {
        println("todo")
    }
}

// 通过关键字 by 建立委托类
class DelegateClass(base: Base) : Base by base


/**
 * 属性委托
 *
 * val/var <属性名>: <类型> by <表达式
 *
 *
 */
class Example {
    var p: String by PropsDelegate()
}


class PropsDelegate {

    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef,get委托属性${property.name}"
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$thisRef,set委托属性${property.name}====value=$value")
    }
}

////////////标准委托//////////////////

/**
 *
 * 1.延迟属性
 * 2.可观察属性
 *observable 可以用于实现观察者模式。

Delegates.observable() 函数接受两个参数: 第一个是初始化值, 第二个是属性值变化事件的响应器(handler)。

在属性赋值后会执行事件的响应器(handler)，它有三个参数：被赋值的属性、旧值和新值：

 */
class User {
    var name: String by Delegates.observable("初始值", { props, old, new ->
        println("${props.name}--$old----$new")
    })
}

/**
 * 3.把属性储存在映射中
 * 如果使用 var 属性，需要把 Map 换成 MutableMap
 */
class Site(map: Map<String, Any?>) {

    val 属性1: String by map

    val 属性2: String by map

}

/**
 * notNull 适用于那些无法在初始化阶段就确定属性值的场合
 */
class Fooo{
    var notNullVar:String by Delegates.notNull()

    /**
     * 局部委托
     */
    fun example(computeFoo:() ->Fooo){
        val memoFooo by lazy(computeFoo)

        memoFooo.doSomething()

    }

    fun doSomething(){
        println("doSomething---$notNullVar")
    }

}


fun main(args: Array<String>) {
    val baseIml = BaseIml()
    DelegateClass(baseIml).todo()

    Example().p.also(::println)

    Example().p = "哈哈"

    val user = User()
    user.name = "第一次赋值"
    user.name = "第二次赋值"

    Site(mapOf(
            "属性1" to "value1",
            "属性2" to "value2"
    )).also {
        println("${it.属性1}---${it.属性2}")
    }

    val f = Fooo()
    f.notNullVar = "notnull"

    f.example {
        println("调用----")
        f
    }

}

